import { Fview, View } from "../gui/UIDefine";
import { Logger } from "../log/logger";
import Pool from "../pool/Pool";
import { AsyncQueue } from "../utils/AsyncQueue";
import PromiseReveal from "../utils/PromiseReveal";
import { SpineVersion } from "./SpineVersion";

export default class SpineItem {

    // private static _pool: Pool<SpineItem>
    static create() {
        // if (!this._pool) {
        //     this._pool = Pool.create(SpineItem);
        // }
        // let item = this._pool.get();
        let item = new SpineItem();

        item._ready = false;
        item._completeTask = new PromiseReveal();
        return item;
    }

    private _sk: Laya.Skeleton | Laya.SpineSkeleton;
    private _templet: Laya.Templet | Laya.SpineTemplet;

    private _taskQueue: AsyncQueue = new AsyncQueue();

    // 是否正在播放
    private _runing: boolean;

    // 动画加载完成
    private _ready: boolean;

    // 是否销毁
    private _destroyed: boolean;
    private _completeTask: PromiseReveal;

    private _version: SpineVersion;

    init(templet: Laya.Templet | Laya.SpineTemplet) {
        if (templet instanceof Laya.SpineTemplet) {
            this._sk = new Laya.SpineSkeleton();
            this._sk.templet = templet;
        } else {
            this._sk = new Laya.Skeleton();
            this._sk.templet = templet;
        }

        this._completeTask.resolve();
        this._ready = true;
    }

    error() {
        this.destroy();
    }

    setP(parent: Fview | Laya.Sprite) {

        this._taskQueue.push((next: Function, p: Laya.Sprite, args) => {
            p.addChild(this._sk);
            next();
        }, parent);

        this.execute();

        return this;
    }

    setXY(x: number, y: number) {
        this._taskQueue.push((next: Function, p: any, args) => {
            this._sk.pos(x, y);
            next();
        })

        this.execute();
        return this;
    }

    play(ani: string | number, sound?: string) {
        this._taskQueue.push((next: Function, params: any, args: any) => {
            this._sk.once(Laya.Event.STOPPED, this, () => next());
            // this._sk.once(Laya.Event.ERROR, this, () => next());
            this._sk.play(ani, false);
        })

        this.execute();
        return this;
    }

    setActive(b: boolean) {
        this._taskQueue.push((next, params, args) => {
            this._sk.active = b;
            this._taskQueue.enable = b;
            if (!b) this._sk.paused();
            next();
        })

        this.execute();

        return this;
    }

    wait(dely: number) {
        this._taskQueue.yieldTime(dely);
        this.execute();

        return this;
    }

    call(fun: Function) {
        if (!fun) return this;

        let queue = this._taskQueue;
        queue.push((next: Function, params: any, args) => {
            fun(args);
            next();
        })

        this.execute();

        return this;
    }

    dispose() {
        this._taskQueue.push((next: Function, params: any, args) => {
            this.recycle();
            next();
        })
        this.execute();
    }


    playNow(ani: string | number, sound?: string) {

        this.clearQueue();
        this.play(ani, sound);

        this.execute();
    }

    stopNow() {

        this.clearQueue();

        if (this._sk) {
            this._sk.stop();
        }
    }


    disposeNow() {
        this._taskQueue.clear();
        this._taskQueue.step();
        this.dispose();
    }

    recycle() {
        this.destroy();

        Pool.put(this);
    }

    get destroyed() {
        return !!this._destroyed;
    }

    get version(): SpineVersion {
        return this._version;
    }

    get originSk() {
        return this._completeTask.then(() => this._sk);
    }

    get x() {
        return this._ready ? this._sk.x : 0;
    }

    set x(value: number) {
        if (!this._ready) return;
        this._sk.x = value;
    }

    get y() {
        return this._ready ? this._sk.y : 0;
    }

    set y(value: number) {
        if (!this._ready) return;
        this._sk.y = value;
    }

    private execute() {
        if (this._runing) {
            return;
        }

        if (!this._completeTask) {
            return;
        }

        if (!this._taskQueue || this._taskQueue.size <= 0) {
            return;
        }

        if (!this._taskQueue.enable) {
            this._taskQueue.enable = true;
        }

        this._runing = true;
        this._completeTask.then(() => this._taskQueue.play());
    }

    private clearQueue() {
        this._taskQueue.clear();
        this._taskQueue.step();

        if (this._sk) {
            this._sk.offAll();
            // this._sk.stop();
        }

        this._runing = false;
    }

    destroy() {

        if (this._destroyed) {
            return;
        }

        if (this._completeTask) {
            this._completeTask.reject();
            this._completeTask = null;
        }

        if (this._taskQueue) {
            this._taskQueue.clear();
            this._taskQueue.step();
            this._runing = false;
            this._taskQueue.enable = false;
            this._taskQueue = null;
        }

        if (this._sk) {
            this._sk.offAll();
            this._sk.stop();
            this._sk.destroy();
            this._sk = null;
        }

        if (this._templet) {
            var _url = this._templet.url;
            this._templet = null;
        }

        this._destroyed = true;
        this._ready = false;

        Logger.logBusiness(_url, "销毁动画");
    }

}